package com.liu.common.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Stream;

/**
 * @Describe 时间工具
 * @Author: guohuaming
 * @Date: 2019/3/14 11:39
 * @Version 1.0
 */
public class DateUtils {

    /**
     * 两个时间相差秒数
     *
     * @param fromDate 开始时间
     * @param toDate   结束时间
     * @return 相差秒数
     */
    public static int secondOfDate(Date fromDate, Date toDate) {
        long from = fromDate.getTime();
        long to = toDate.getTime();
        long v = to - from;
        return (int) (v / 1000L);
    }

    /**
     * 两个时间相差分钟数
     *
     * @param fromDate 开始时间
     * @param toDate   结束时间
     * @return 相差分钟数
     */
    public static int minuteOfDate(Date fromDate, Date toDate) {
        long from = fromDate.getTime();
        long to = toDate.getTime();
        long v = to - from;
        return (int) (v / 1000L / 60L);
    }

    /**
     * 两个时间相差小时数
     *
     * @param fromDate 开始时间
     * @param toDate   结束时间
     * @return 相差小时数
     */
    public static int hourOfDate(Date fromDate, Date toDate) {
        long from = fromDate.getTime();
        long to = toDate.getTime();
        long v = to - from;
        return (int) (v / 1000L / 60L / 60L);
    }

    /**
     * 两个时间相差天数
     *
     * @param fromDate 开始时间
     * @param toDate   结束时间
     * @return 相差天数
     */
    public static int yearOfDate(Date fromDate, Date toDate) {
        Calendar from = Calendar.getInstance();
        Calendar to = Calendar.getInstance();
        from.setTime(fromDate);
        to.setTime(toDate);
        return to.get(1) - from.get(1);
    }


    /**
     * 两个时间相差月数
     *
     * @param fromDate 开始时间
     * @param toDate   结束时间
     * @return 相差月数
     */
    public static int monthOfDate(Date fromDate, Date toDate) {
        Calendar from = Calendar.getInstance();
        Calendar to = Calendar.getInstance();
        from.setTime(fromDate);
        to.setTime(toDate);
        int year = to.get(1) - from.get(1);
        return (year * 12 + to.get(2)) - from.get(2);
    }

    /**
     * 两个时间相差年数
     *
     * @param fromDate 开始时间
     * @param toDate   结束时间
     * @return 相差年数
     */
    public static int dayOfDate(Date fromDate, Date toDate) {
        long from = fromDate.getTime();
        long to = toDate.getTime();
        long v = to - from;
        return (int) (v / 1000L / 3600L / 24L);
    }

    /**
     * 在一个时间基础上增加秒数
     *
     * @param date   原时间
     * @param second 秒
     * @return 增加后的时间
     */
    public static Date addSecond(Date date, int second) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(13, calendar.get(13) + second);
        return calendar.getTime();
    }

    /**
     * 在一个时间基础上增加分钟
     *
     * @param date   原时间
     * @param minute 分钟
     * @return 增加后的时间
     */
    public static Date addMinute(Date date, int minute) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(12, calendar.get(12) + minute);
        return calendar.getTime();
    }

    /**
     * 在一个时间基础上增加小时
     *
     * @param date 原时间
     * @param hour 小时
     * @return 增加后的时间
     */
    public static Date addHour(Date date, int hour) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(11, calendar.get(11) + hour);
        return calendar.getTime();
    }

    /**
     * 在一个时间基础上增加天数
     *
     * @param date 原时间
     * @param day  天数
     * @return 增加后的时间
     */
    public static Date addDay(Date date, int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(6, calendar.get(6) + day);
        return calendar.getTime();
    }

    /**
     * 在一个时间基础上增加月数
     *
     * @param date  原时间
     * @param month 月
     * @return 增加后的时间
     */
    public static Date addMonth(Date date, int month) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(2, calendar.get(2) + month);
        return calendar.getTime();
    }

    /**
     * 在一个时间基础上增加年数
     *
     * @param date 原时间
     * @param year 年
     * @return 增加后的时间
     */
    public static Date addYear(Date date, int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(1, calendar.get(2) + year);
        return calendar.getTime();
    }

    /**
     * 根据给定的数据创建一个时间
     *
     * @param year  年
     * @param month 月
     * @param day   日
     * @return 时间
     */
    public static Date newDate(int year, int month, int day) {
        return newDate(year, month, day, 0, 0, 0);
    }

    /**
     * 根据给定的数据创建一个时间
     *
     * @param year   年
     * @param month  月
     * @param day    日
     * @param hour   时
     * @param minute 分
     * @param second 秒
     * @return 时间
     */
    public static Date newDate(int year, int month, int day, int hour, int minute, int second) {
        Calendar c = Calendar.getInstance();
        c.set(1, year);
        c.set(2, month - 1);
        c.set(5, day);
        c.set(11, hour);
        c.set(12, minute);
        c.set(13, second);
        c.set(14, 999);
        return c.getTime();
    }


    /**
     * @param dateStr 日期字符串
     * @return 将String日期转换成 java.util.Date
     * @throws ParseException .
     */
    public static Date StringToDate(String dateStr) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        dateFormat.setLenient(false);
        return dateFormat.parse(dateStr);
    }

    /**
     * @param dateStr 日期字符串
     * @param dateFormatType
     * @return 将String日期转换成 java.util.Date
     * @throws ParseException .
     */
    public static Date StringToDate(String dateStr,String dateFormatType) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatType);
        dateFormat.setLenient(false);
        return dateFormat.parse(dateStr);
    }

    /**
     * 截取日期数据的时、分、秒
     *
     * @param date 时间
     * @return 分割后的日期
     */
    public static String dateSplit(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("HH时mm分");
        return format.format(date);
    }



    /**
     * @param date 日期
     * @return 将日期转换成 String ， 格式是 yyyy-MM-dd HH:mm:ss
     */
    public static String dateToString(Date date) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        dateFormat.setLenient(false);
        return dateFormat.format(date);
    }

    /**
     * @param date 日期
     * @return 将日期转换成 String ， 格式是 yyyy-MM-dd     *
     */
    public static String dateToShortDateString(Date date) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        dateFormat.setLenient(false);
        return dateFormat.format(date);
    }

    /**
     * 将日期转换成 String
     * @param date 日期
     * @param  dateFormatType 指定格式  如 yyyy-MM-dd HH:mm:ss
     * @return  返回指定格式的String
     */
    public static String getDateFormat(Date date, String dateFormatType) {
        SimpleDateFormat simformat = new SimpleDateFormat(dateFormatType);
        return simformat.format(date);
    }

    /**
     * 将日期转换成 String
     * @param dateStr 日期  Thu Mar 14 11:46:18 CST 2019
     * @param  format 指定格式  如 yyyy-MM-dd HH:mm:ss
     * @return  返回指定格式的String
     *例如  Thu Mar 14 11:46:03 CST 2019 -> 2019-03-14 11:46:03
     */
    public static String formatCSTTime(String dateStr, String format) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
        Date d = sdf.parse(dateStr);
        return DateUtils.getDateFormat(d, format);
    }

    public static TimeZone getTimeZone() {
        TimeZone timeZone =TimeZone.getTimeZone("Asia/Shanghai");
        return timeZone;
    }



    /**
     * 根据两个时间查询中间月份集合
     * @param minDate
     * @param maxDate
     * @return
     * @throws ParseException
     */
    public static List<String> getMonthBetween(String minDate, String maxDate) throws ParseException {
        ArrayList<String> result = new ArrayList<String>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");//格式化为年月
        Calendar min = Calendar.getInstance();
        Calendar max = Calendar.getInstance();

        min.setTime(sdf.parse(minDate));
        min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);

        max.setTime(sdf.parse(maxDate));
        max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);

        Calendar curr = min;
        while (curr.before(max)) {
            result.add(sdf.format(curr.getTime()));
            curr.add(Calendar.MONTH, 1);
        }

        return result;
    }

    /**
     * @return java.util.List<java.lang.String>
     * @Author liangjiayao
     * @Description 两个日期之间的所有日期集合
     * @Date 2019/11/18 16:11
     * @Param [startTime, endTime]
     **/
    public static List<String> getBetweenDate(String startTime, String endTime) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 声明保存日期集合
        List<String> list = new ArrayList<String>();
        try {
            // 转化成日期类型
            Date startDate = sdf.parse(startTime);
            Date endDate = sdf.parse(endTime);

            //用Calendar 进行日期比较判断
            Calendar calendar = Calendar.getInstance();
            while (startDate.getTime() <= endDate.getTime()) {
                // 把日期添加到集合
                list.add(sdf.format(startDate));
                // 设置日期
                calendar.setTime(startDate);
                //把日期增加一天
                calendar.add(Calendar.DATE, 1);
                // 获取增加后的日期
                startDate = calendar.getTime();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }


    /**
     * 把long 转换成 日期 再转换成String类型
     */
    public static String transferLongToDate(String dateFormat, Long millSec) {
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        Date date = new Date(millSec*1000);
        return sdf.format(date);
    }

    /**
     * 把long 转换成 日期
     */
    public static Date transferLongToDate(Long millSec) {
        return new Date(millSec*1000);
    }

    /**
     *获取时间段所有天的LIST
     * @param startTime  开始日期
     * @param endTime  终止日期
     * @param formatType  日期格式
     * @return
     */
    public static List<String> getDays(String startTime, String endTime ,String formatType) {
        // 返回的日期集合
        List<String> days = new ArrayList<String>();
        SimpleDateFormat dateFormat = new SimpleDateFormat(formatType);
        try {
            Date start = dateFormat.parse(startTime);
            Date end = dateFormat.parse(endTime);
            Calendar tempStart = Calendar.getInstance();
            tempStart.setTime(start);
            Calendar tempEnd = Calendar.getInstance();
            tempEnd.setTime(end);
            tempEnd.add(Calendar.DATE, +1);// 日期加1(包含结束)
            while (tempStart.before(tempEnd)) {
                days.add(dateFormat.format(tempStart.getTime()));
                tempStart.add(Calendar.DAY_OF_YEAR, 1);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return days;
    }

    /**
     * 获取本月第一天
     * @return
     */
    public static String getmindate(){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
        Date time = calendar.getTime();
        String firstDay = DateUtils.dateToString(calendar.getTime());
        return firstDay;
    }

    /**
     * 获取本月最后一天
     * @return
     */
    public static String getmaxdate(){
        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTime(new Date());
        calendar2.set(Calendar.DAY_OF_MONTH, calendar2.getActualMaximum(Calendar.DAY_OF_MONTH));
        String lastDay = DateUtils.dateToString(calendar2.getTime());
        return lastDay;
    }


    public static Integer getDifMonth(Date startDate, Date endDate){
        Calendar start = Calendar.getInstance();
        Calendar end = Calendar.getInstance();
        start.setTime(startDate);
        end.setTime(endDate);
        int result = end.get(Calendar.MONTH) - start.get(Calendar.MONTH);
        int month = (end.get(Calendar.YEAR) - start.get(Calendar.YEAR)) * 12;
        return Math.abs(month + result);
    }


    /**
     * 获得当天零时零分零秒
     * @return
     */
    public static Date initDateByDay(){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    /**
     * 计算两个日期之间相差的天数
     * @param smdate 较小的时间
     * @param bdate 较大的时间
     * @return 相差天数
     *
     */
    public static int daysBetween(Date smdate,Date bdate) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        long between_days=(time2-time1)/(1000*3600*24);
        return Integer.parseInt(String.valueOf(between_days));
    }

    /**
     * 计算时间相差天数
     * @param startTime ： 开始时间
     * @param endTime  ： 结束时间
     * @return
     */
    public static int caculateDaysDifference(String startTime,String endTime) {
        SimpleDateFormat formatter =  new SimpleDateFormat( "yyyy-MM-dd");
        Date date1=null;
        Date date = null;
        Long l = 0L;
        try {
            date = formatter.parse(startTime);
            long ts = date.getTime();
            date1 =  formatter.parse(endTime);
            long ts1 = date1.getTime();
            l = (ts - ts1) / (1000 * 60 * 60 * 24);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return l.intValue();
    }

    /**
     * 格式化字符串为日期
     *
     * @param date
     * @param format
     * @return
     */
    public static Date parseDate(String date, String format) {
        try {
            return new SimpleDateFormat(format).parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 比较日期
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static int compareDate(String startTime, String endTime) throws ParseException {
        SimpleDateFormat formatter =  new SimpleDateFormat( "yyyy-MM-dd");
        Date start = formatter.parse(startTime);
        Date end = formatter.parse(endTime);
        if (start.getTime() > end.getTime()){
            return -1;
        } else if (start.getTime() < end.getTime()){
            return 1;
        } else {
            return 0;
        }
    }

    /**
     * 计算时间
     * @param startTime ： 开始时间
     * @param endTime  ： 结束时间
     * @return
     */
    public static int caculateTotalTime(String startTime,String endTime) {
        SimpleDateFormat formatter =  new SimpleDateFormat( "yyyy-MM-dd");
        Date date1=null;
        Date date = null;
        Long l = 0L;
        try {
            date = formatter.parse(startTime);
            long ts = date.getTime();
            date1 =  formatter.parse(endTime);
            long ts1 = date1.getTime();
            l = (ts - ts1) / (1000 * 60 * 60 * 24);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        //不足一天按一天算
        return l.intValue()>0?l.intValue():1;
    }

    public static int compareDate(Date startTime, Date endTime) {
        if (startTime.getTime() > endTime.getTime()){
            return -1;
        } else if (startTime.getTime() < endTime.getTime()){
            return 1;
        } else{
            return 0;
        }
    }

    /**
     * 获取间隔的日期列表
     *
     * @param preDate 开始日期
     * @param endDate 截止日期
     * @return
     */
    private static List<LocalDate> getRangeDays(LocalDate preDate, LocalDate endDate) {
        List<LocalDate> dates = new ArrayList<>();
        //间隔的天数
        long betweenDays = ChronoUnit.DAYS.between(preDate, endDate);
        if (betweenDays < 1) {
            //开始日期<=截止日期
            return dates;
        }
        //创建一个从开始日期、每次加一天的无限流，限制到截止日期为止
        Stream.iterate(preDate, c -> c.plusDays(1))
                .limit(betweenDays + 1)
                .forEach(dates::add);
        return dates;
    }

    /**
     * 获取东八区时间
     * @return
     */
    public static Date getGMT8Time(){
        Date gmt8 = null;
        try {
            Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"), Locale.CHINESE);
            Calendar day = Calendar.getInstance();
            day.set(Calendar.YEAR, cal.get(Calendar.YEAR));
            day.set(Calendar.MONTH, cal.get(Calendar.MONTH));
            day.set(Calendar.DATE, cal.get(Calendar.DATE));
            day.set(Calendar.HOUR_OF_DAY, cal.get(Calendar.HOUR_OF_DAY));
            day.set(Calendar.MINUTE, cal.get(Calendar.MINUTE));
            day.set(Calendar.SECOND, cal.get(Calendar.SECOND));
            gmt8 = day.getTime();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return  gmt8;
    }

    public static void main(String[] args) throws ParseException {
        System.out.println(getGMT8Time());
    }
}
